#ifndef _QUERY_HH
#define _QUERY_HH


#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <set>

using std::cout;
using std::endl;
using std::ostream;
using std::ifstream;
using std::istringstream;
using std::shared_ptr;
using std::string;
using std::map;
using std::set;
using std::vector;

// abstract class acts as a base class for concrete query types; all members are private
class Query_base 
{
    friend class Query;  
protected:
    typedef TextQuery::line_no line_no; // used in the eval functions
    virtual ~Query_base() { }
private:
    // eval returns the QueryResult that matches this Query
    virtual QueryResult eval(const TextQuery&) const = 0; 
    // rep is a string representation of the query
	virtual std::string rep() const = 0;
};


// interface class to manage the Query_base inheritance hierarchy
class Query
{
    // these operators need access to the shared_ptr constructor
    friend Query operator~(const Query &);
    friend Query operator|(const Query&, const Query&);
    friend Query operator&(const Query&, const Query&);
public:
    Query(const std::string&);  // builds a new WordQuery

    // interface functions: call the corresponding Query_base operations
    QueryResult eval(const TextQuery &t) const 
	{
		return q->eval(t); 
	}

	std::string rep() const 
	{ 
		return q->rep(); 
	}
private:
    Query(std::shared_ptr<Query_base> query)
	: q(query)
	{ 

	}
    std::shared_ptr<Query_base> q;
};


class QueryResult;

//TextQuery 只负责查询,查询结果的展示交给QueryResult
class TextQuery
{
public:
	//typedef std::vector<std::string>::size_type line_no;
    using line_no = vector<string>::size_type;

	TextQuery(ifstream& ifs);   // 读文件按行存到vector中
    QueryResult query(const string&) const; 
    void display_map(); // 测试是否插入成功

private:
    shared_ptr<vector<string>> _lines;
    map<string, shared_ptr<set<size_t>>> _dict;

    static string cleanup_str(const string&);   // 除去非法字符和统一大小写
};

#endif

#ifndef _QUERY_RESULT_HH
#define _QUERY_RESULT_HH

class QueryResult 
{
	friend ostream& print(ostream&, const QueryResult&);
public:

	QueryResult(string s, shared_ptr<set<size_t>> p, shared_ptr<vector<string>> f);

    // 出现的行数
	size_t size() const { return _lineNum->size(); }
    // 第一次出现的行
	set<size_t>::const_iterator begin() const { return _lineNum->begin(); }
    // 最后一次出现的行
	set<size_t>::const_iterator end() const { return _lineNum->end(); }
    // 得到全文
	std::shared_ptr<vector<string> > get_file() { return _lines; }

private:
	string _word;  // word this query represents
	shared_ptr<set<size_t> > _lineNum; // lines it's on
	shared_ptr<vector<string> > _lines;  //input file
};

#endif



#ifndef _WORD_QUERY_HH
#define _WORD_QUERY_HH

class WordQuery
    : public Query_base 
{
    friend class Query; // Query uses the WordQuery constructor
    WordQuery(const string& word) : _word(word){ }

    // 将 word 的查询结果返回
    QueryResult eval(const TextQuery& txt) const { return txt.query(_word); }
    // 不知道干啥的
	string rep() const { return _word; }

    string _word;   // 要搜索的单词
};

#endif



#ifndef _NOT_QUERY_HH
#define _NOT_QUERY_HH

class NotQuery
    : public Query_base 
{
    friend Query operator~(const Query&);

    NotQuery(const Query &q)
	: query(q) 
	{

	}

    // concrete class: NotQuery defines all inherited pure virtual functions
	string rep() const 
	{
		return "~(" + _query.rep() + ")";
	}

    QueryResult eval(const TextQuery&) const;

    Query _query;
};


#endif

